package servlet;

import impl.ClientProxyImpl;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 * Servlet Class which handles Communication with Clients over HTTP.
 * TODO: implement URL Rewriting
 * @author Steffen Gruschka, Dominik Korittki
 */
@WebServlet(name = "ClientServlet", urlPatterns = {"/ClientServlet"})
public class ClientServlet extends HttpServlet {
    
    String ip = "127.0.0.1";
    HashMap<String, ClientProxyImpl> clientProxyList = new HashMap<String, ClientProxyImpl>();
    HashMap<String, ArrayList<String>> clientMessageList = new HashMap<String, ArrayList<String>>();

    /**
     * Processes requests for both HTTP
     * <code>GET</code> and
     * <code>POST</code> methods.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        
        try {
            String operation = request.getParameterValues("operation")[0];
            if(operation != null) {
                
                
                /*----------------------------------------------
                 * Login
                 *----------------------------------------------*/
                if(operation.equals("login")) {
                    String username = request.getParameterValues("username")[0];
                    if(username.equals("")) {
                        printError(out, "Keinen Usernamen eingegeben.");
                        return;
                    }
                    try {
                        //Create messagelist for each client
                        ArrayList<String> messageList = new ArrayList<String>();
                        clientMessageList.put(username, messageList);
                        
                        //Create clientproxy object for each client
                        ClientProxyImpl clientProxy = new ClientProxyImpl(username, "127.0.0.1", this);
                        clientProxyList.put(username, clientProxy);
                    } catch(Exception e) {
                        printError(out, "Server nicht erreichbar.");
                        return;
                    }
                    
                    //generate session
                    HttpSession session = request.getSession(true);
                    session.setAttribute("username", username);
                    
                    printChat(out, response, username);
                  
                    
                /*----------------------------------------------
                 * Send message to server
                 *----------------------------------------------*/
                } else if(operation.equals("sendmsg")) {
                    HttpSession session = request.getSession(false);
                    
                    if(session == null) {
                        printError(out, "Keine g&uuml;ltige Session gefunden");
                        return;
                    }
                    
                    String username = (String) session.getAttribute("username");
                    ClientProxyImpl clientProxy = clientProxyList.get(username);
                    
                    if(clientProxy == null) {
                        printError(out, "Session Problem: Username nicht gefunden");
                        return;
                    }
                    
                    String usermsg = request.getParameterValues("usermsg")[0];
                    clientProxy.sendMessage(usermsg);
                    
                    printChat(out, response, username);
                    
                    
                /*----------------------------------------------
                 * Show messages
                 *----------------------------------------------*/
                } else if(operation.equals("showmsg")) {
                    HttpSession session = request.getSession(false);
                    
                    if(session == null) {
                        printError(out, "Keine g&uuml;ltige Session gefunden");
                        return;
                    }
                    
                    String username = (String) session.getAttribute("username");
                    printChat(out, response, username);
                
                /*----------------------------------------------
                 * Logout
                 *----------------------------------------------*/
                } else if(operation.equals("logout")) {
                    HttpSession session = request.getSession(false);
                    if(session == null) {
                        printError(out, "Keine g&uuml;ltige Session gefunden");
                        return;
                    }
                    
                    String username = (String) session.getAttribute("username");
                    ClientProxyImpl clientProxy = clientProxyList.get(username);
                    ArrayList<String> messageList = clientMessageList.get(username);
                    
                    if(clientProxy == null || messageList == null) {
                        printError(out, "Session Problem: Username nicht gefunden");
                        return;
                    }
                    
                    clientProxy.logout();
                    clientProxyList.remove(username);
                    clientMessageList.remove(username);
                    
                    String logoutmsg;
                    logoutmsg = "Erfolgreich ausgeloggt."
                            + "Zur&uuml;ck zum "
                            + "<a href=\"index.html \">Login</a>?";
                    printNotice(out, logoutmsg);
                    
                    session.invalidate();
                }
            
            //If there is no known operation set
            } else {
                printError(out, "Keine g&uuml;ltige Operation gesetzt.");
            }
        } finally {            
            out.close();
        }
    }
    
    

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP
     * <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP
     * <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>

    /**
     * Prints html page with an error message
     * @param out stream to which to write
     * @param message message which should be displayed
     */
    private void printError(PrintWriter out, String message) {
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Error</title>");            
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Fehler:</h1>");
        out.println("<p>" + message + "</p>");
        out.println("</body>");
        out.println("</html>");
    }
    
    /**
     * Prints html page with an notice message
     * @param out stream to which to write
     * @param message message which should be displayed
     */
    private void printNotice(PrintWriter out, String message) {
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Notice</title>");            
        out.println("</head>");
        out.println("<body>");
        out.println("<h1>Notice:</h1>");
        out.println("<p>" + message + "</p>");
        out.println("</body>");
        out.println("</html>");
    }
    
    /**
     * Outputs the chat as html page
     * @param out stream to which to write
     * @param response response object (only for url rewriting)
     * @param username user to whom the output goes
     */
    private void printChat(PrintWriter out, HttpServletResponse response, String username) {
        ArrayList<String> messageList = clientMessageList.get(username);
        if(messageList == null) {
            printError(out, "Session Problem: Username nicht gefunden");
            return;
        }
        
        String messageOutput = "";
        for(String actMessage : messageList) {
            messageOutput += actMessage + "\r\n";
        }
        
        out.println("<html>");
        out.println("<head>");
        out.println("<title>The Chat</title>"); 
        out.println("<meta http-equiv=\"refresh\" content=\"10;"
                + "URL=ClientServlet?username=" 
                + username
                + "&operation=showmsg\">");
        out.println("</head>");
        out.println("<body>");
        out.print("<form action=\"");
        out.print("ClientServlet"); //URL Rewriting noch hinzufuegen
        out.println("\" method=\"POST\">");
        out.println("<div>");
        out.println("<input type=\"hidden\" name=\"operation\" value=\"sendmsg\" />");
        out.println("<textarea name=\"chatoutput\" cols=\"50\" rows=\"10\" readonly>"
                + messageOutput
                + "</textarea><br />");
        out.println("<input type=\"text\" name=\"usermsg\" />");
        out.println("<input type=\"submit\" value=\"Absenden\" />");
        out.println("</div>");
        out.println("</form>");
        
        out.print("<form action=\"");
        out.print("ClientServlet"); //URL Rewriting noch hinzufuegen
        out.println("\" method=\"POST\">");
        out.println("<div>");
        out.println("<input type=\"hidden\" name=\"operation\" value=\"logout\" />");
        out.println("<input type=\"submit\" value=\"Logout\" />");
        out.println("</div>");
        out.println("</form>");
        
        out.println("</body>");
        out.println("</html>");
    }
    
    /**
     * Stores incoming messages to the appropriate client
     * @param username username of whom the message comes
     * @param message message of the client who´s sending the message
     * @param clientName appropriate client
     */
    public void storeMessage(String username, String message, String clientName) {
        ArrayList<String> actMessageList = clientMessageList.get(clientName);

        SimpleDateFormat sdf = new SimpleDateFormat();
        sdf.applyPattern( "hh:mm:ss" );
        String datum = sdf.format(new Date());

        actMessageList.add(username + " " + datum + ": " + message);
        
        
    }
}
